﻿using System;

namespace BlueSky
{
    /// <summary>
    /// IoC container interface.
    /// </summary>
    public interface IIoCContainer : IDisposable
    {
        /// <summary>
        /// Resolve an instance of the default requested type from the container.
        /// </summary>
        /// <param name="type">Type of object to get from the container.</param>
        /// <returns>The retrieved object.</returns>
        object Resolve(Type type);

        /// <summary>
        /// Resolve an instance of the requested type with the given name from the container.
        /// </summary>
        /// <param name="type">Type of object to get from the container.</param>
        /// <param name="name">Name of the object to retrieve.</param>
        /// <returns>The retrieved object.</returns>
        object Resolve(Type type, string name);

        /// <summary>
        /// Resolve an instance of the default requested type from the container.
        /// </summary>
        /// <typeparam name="T">Type of object to get from the container.</typeparam>
        /// <returns>The retrieved object.</returns>
        T Resolve<T>();

        /// <summary>
        /// Resolve an instance of the requested type with the given name from the container.
        /// </summary>
        /// <typeparam name="T">Type of object to get from the container.</typeparam>
        /// <param name="name">Name of the object to retrieve.</param>
        /// <returns>The retrieved object.</returns>
        T Resolve<T>(string name);

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <typeparam name="TFrom">Type that will be requested.</typeparam>
        /// <typeparam name="TTo">Type that will actually be returned.</typeparam>
        void Register<TFrom, TTo>() where TTo : TFrom;

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <typeparam name="TFrom">Type that will be requested.</typeparam>
        /// <typeparam name="TTo">Type that will actually be returned.</typeparam>
        /// <param name="name">Name of the object to retrieve.</param>
        void Register<TFrom, TTo>(string name) where TTo : TFrom;

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <param name="typeForm">Type that will be requested.</param>
        /// <param name="typeTo">Type that will actually be returned.</param>
        void Register(Type typeForm, Type typeTo);

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <param name="typeForm">Type that will be requested.</param>
        /// <param name="typeTo">Type that will actually be returned.</param>
        /// <param name="name">Name of the object to retrieve.</param>
        void Register(Type typeForm, Type typeTo, string name);

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <typeparam name="T">Type of instance to register</typeparam>
        /// <param name="instance">Object to returned.</param>
        void Register<T>(T instance);

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <typeparam name="T">Type of instance to register</typeparam>
        /// <param name="instance">Object to returned.</param>
        /// <param name="name">Name of the object to retrieve.</param>
        void Register<T>(T instance, string name);

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <param name="type">Type of instance to register.</param>
        /// <param name="instance">Object to returned.</param>
        void Register(Type type, object instance);

        /// <summary>
        /// A type mapping with the container.
        /// </summary>
        /// <param name="type">Type of instance to register.</param>
        /// <param name="instance">Object to returned.</param>
        /// <param name="name">Name of the object to retrieve.</param>
        void Register(Type type, object instance, string name);        
    }
}
